package com.ihr360.oneclick.service.impl;

import com.ihr360.oneclick.constant.ConstantString;
import com.ihr360.oneclick.dao.OneClickTermDao;
import com.ihr360.oneclick.dao.OneClickTermMetaDao;
import com.ihr360.oneclick.dao.OneClickTermMetaTemplateDao;
import com.ihr360.oneclick.dao.SpreadsheetDao;
import com.ihr360.oneclick.dao.SpreadsheetRowDao;
import com.ihr360.oneclick.dto.OneClickTermDto;
import com.ihr360.oneclick.dto.OneClickTermMetaDto;
import com.ihr360.oneclick.dto.OneClickTermMetaTemplateDto;
import com.ihr360.oneclick.dto.spreadsheet.SpreadsheetDto;
import com.ihr360.oneclick.entity.OneClickTerm;
import com.ihr360.oneclick.entity.RowHeaderColumn;
import com.ihr360.oneclick.exception.OneClickException;
import com.ihr360.oneclick.request.SearchRequest;
import com.ihr360.oneclick.service.OneClickTermService;
import com.ihr360.oneclick.service.SpreadsheetService;
import com.ihr360.oneclick.util.BeanConvertUtils;
import com.ihr360.oneclick.util.PageableUtils;
import com.ihr360.oneclick.vo.PageData;
import com.ihr360.rest.service.MessageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.alibaba.fastjson.JSON.parseArray;

/**
 * @author tom
 * @date 17-12-18
 */
@Service
public class OneClickTermServiceImpl implements OneClickTermService {

    @Autowired
    private OneClickTermDao oneClickTermDao;
    @Autowired
    private OneClickTermMetaDao oneClickTermMetaDao;
    @Autowired
    private MessageService messageService;
    @Autowired
    private SpreadsheetRowDao spreadsheetRowDao;
    @Autowired
    private SpreadsheetDao spreadsheetDao;
    @Autowired
    private OneClickTermMetaTemplateDao oneClickTermMetaTemplateDao;
    @Autowired
    private SpreadsheetService spreadsheetService;

    private Specification<OneClickTermDto> buildSpecification(String companyId) {
        return (root, cq, cb) -> {
            Predicate predicate = cb.conjunction();
            List<Expression<Boolean>> expressionList = predicate.getExpressions();
            List<String> companyIdList = new ArrayList<>();
            companyIdList.add(companyId);
            companyIdList.add(ConstantString.SYSTEM_DEFAULT_COMPANY_ID);
            CriteriaBuilder.In<String> in = cb.in(root.get("companyId"));
            companyIdList.forEach(in::value);
            expressionList.add(in);
            return predicate;
        };
    }

    @Override
    public PageData<OneClickTerm> getPageData(String companyId, SearchRequest searchRequest) {
        Page<OneClickTermDto> page = oneClickTermDao.findAll(buildSpecification(companyId),
                PageableUtils.generatePageable(searchRequest));
        PageData<OneClickTerm> pageData = new PageData<>(page);
        List<OneClickTerm> content = new ArrayList<>();
        page.getContent().forEach(oneClickTermDto ->
                content.add(BeanConvertUtils.convertFor(oneClickTermDto, new OneClickTerm()))
        );
        pageData.setContent(content);
        return pageData;
    }

    @Override
    public List<OneClickTerm> getTermListByEnable(String companyId, boolean enable) {
        List<String> companyIdList = new ArrayList<>();
        companyIdList.add(companyId);
        companyIdList.add(ConstantString.SYSTEM_DEFAULT_COMPANY_ID);
        List<OneClickTermDto> oneClickTermDtoList = oneClickTermDao.findByCompanyIdInAndEnableOrderByCreatedAtAsc(companyIdList, enable);
        List<OneClickTerm> oneClickTermList = new ArrayList<>();
        if (CollectionUtils.isEmpty(oneClickTermDtoList)) {
            return oneClickTermList;
        }
        oneClickTermDtoList.forEach(oneClickTermDto -> {
            OneClickTerm oneClickTerm = new OneClickTerm();
            BeanConvertUtils.convertFor(oneClickTermDto, oneClickTerm);
            oneClickTermList.add(oneClickTerm);
        });
        return oneClickTermList;
    }

    @Override
    public OneClickTerm getOneClickTermById(String termId) {
        OneClickTermDto oneClickTermDto = oneClickTermDao.findOne(termId);
        return BeanConvertUtils.convertFor(oneClickTermDto, new OneClickTerm());
    }

    private void validateTerm(OneClickTerm term){
        if(StringUtils.isEmpty(term.getCompanyId())){
            throw new OneClickException("one_click_term_company_is_null", "公司不能为空!");
        }
        String termId = term.getId();
        if(termId == null) {
            if(oneClickTermDao.countByCompanyIdAndTermName(term.getCompanyId(), term.getTermName()) >0) {
                throw new OneClickException("one_click_term_existent", "功能已存在！");
            }
        } else {
            if(oneClickTermDao.countByCompanyIdAndTermNameAndIdNot(term.getCompanyId(), term.getTermName(), termId) >0) {
                throw new OneClickException("one_click_term_existent", "功能已存在！");
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public OneClickTerm saveOneClickTerm(OneClickTerm term) {
        validateTerm(term);
        OneClickTermDto oneClickTermDto = BeanConvertUtils.convertFor(term, new OneClickTermDto());
        if (oneClickTermDto.getId() != null) {
            OneClickTermDto targetOneClickTerm = oneClickTermDao.findOne(term.getId());
            if (ConstantString.SYSTEM_DEFAULT_COMPANY_ID.equals(targetOneClickTerm.getCompanyId())) {
                // 系统默认一键功能，不允许编辑
                throw new OneClickException("one_click_system_term_unable_to_edit", "系统默认一键功能，不允许编辑!");
            }
            oneClickTermDto.setTermMetaList(targetOneClickTerm.getTermMetaList());
            oneClickTermDto.setUpdatedAt(new Date());
            oneClickTermDto = oneClickTermDao.save(oneClickTermDto);
        } else {
            oneClickTermDto.setCreatedAt(new Date());
            oneClickTermDao.save(oneClickTermDto);

            // 获取系统电子表格表头模板
            OneClickTermMetaTemplateDto columnTemplate =
                    oneClickTermMetaTemplateDao.findByMetaKey(ConstantString.SPREAD_SHEET_COLUMN_META_KEY);
            OneClickTermMetaDto columnTemplateDao = BeanConvertUtils.convertFor(columnTemplate, new OneClickTermMetaDto());
            columnTemplateDao.setId(null);
            columnTemplateDao.setCreatedAt(new Date());
            columnTemplateDao.setTermId(oneClickTermDto.getId());

            OneClickTermMetaTemplateDto tipTemplate =
                    oneClickTermMetaTemplateDao.findByMetaKey(ConstantString.ONE_CLICK_TIP_TEMPLATE);
            OneClickTermMetaDto tipTermMetaDto = BeanConvertUtils.convertFor(tipTemplate, new OneClickTermMetaDto());
            tipTermMetaDto.setId(null);
            tipTermMetaDto.setCreatedAt(new Date());
            tipTermMetaDto.setTermId(oneClickTermDto.getId());

            OneClickTermMetaTemplateDto tipTemplateEn =
                    oneClickTermMetaTemplateDao.findByMetaKey(ConstantString.ONE_CLICK_TIP_TEMPLATE_EN);
            OneClickTermMetaDto tipTermMetaEnDto = BeanConvertUtils.convertFor(tipTemplateEn, new OneClickTermMetaDto());
            tipTermMetaEnDto.setId(null);
            tipTermMetaEnDto.setCreatedAt(new Date());
            tipTermMetaEnDto.setTermId(oneClickTermDto.getId());

            List<OneClickTermMetaDto> oneClickTermMetaDtoList = new ArrayList<>();
            oneClickTermMetaDtoList.add(columnTemplateDao);
            oneClickTermMetaDtoList.add(tipTermMetaDto);
            oneClickTermMetaDtoList.add(tipTermMetaEnDto);
            oneClickTermMetaDao.save(oneClickTermMetaDtoList);
        }
        return BeanConvertUtils.convertFor(oneClickTermDto, term);
    }

    @Override
    public void deleteOneClickTerm(String companyId, String termId) {
        OneClickTermDto targetOnclickTerm = oneClickTermDao.findOne(termId);
        if (targetOnclickTerm == null) {
            throw new OneClickException("one_click_term_not_find", "未找到对应一键功能!");
        }
        if (ConstantString.SYSTEM_DEFAULT_COMPANY_ID.equals(targetOnclickTerm.getCompanyId())) {
            throw new OneClickException("one_click_system_term_unable_to_delete", "系统默认一键功能，不允许删除!");
        }
        if (targetOnclickTerm.getEnable()) {
            // 启用状态不能删除
            throw new OneClickException("one_click_term_enable_unable_to_delete", "启用状态，不能删除!");
        }
        long rowCount = spreadsheetRowDao.countByCompanyIdAndTermId(companyId, termId);
        if(rowCount > 0) {
            throw new OneClickException("one_click_term_Published_unable_to_delete", "已经发布过内容，不能删除!");
        }

        // 删除导入草稿
        List<SpreadsheetDto> spreadsheetDtoList = spreadsheetDao.findByTermId(termId);
        if (!CollectionUtils.isEmpty(spreadsheetDtoList)) {
            spreadsheetService.deleteSpreadsheetBatch(spreadsheetDtoList.stream().map(SpreadsheetDto::getId).collect(Collectors.toList()));
        }
        oneClickTermMetaDao.deleteByTermId(termId);
        oneClickTermDao.delete(termId);
    }

    @Override
    public List<RowHeaderColumn> getSpreadSheetColumn(String termId, String local) {
        OneClickTermMetaDto oneClickTermMetaDto =
                oneClickTermMetaDao.findByTermIdAndMetaKey(termId, ConstantString.SPREAD_SHEET_COLUMN_META_KEY);
        if (oneClickTermMetaDto == null) {
            throw new OneClickException("one_click_term_meta_config_error", "系统配置异常，请联系管理员！");
        }
        String columnMetaValue = oneClickTermMetaDto.getMetaValue();
        List<RowHeaderColumn> rowHeaderColumnList = parseArray(columnMetaValue, RowHeaderColumn.class);
        String[] i18nKeyList = (String[]) rowHeaderColumnList.stream().map(RowHeaderColumn::getColumni8nKey).toArray();
        Map<String, String> i18nInfoMap = messageService.messagesMap(local, i18nKeyList);
        rowHeaderColumnList.forEach(rowHeaderColumn -> {
            String displayName = i18nInfoMap.get(rowHeaderColumn.getColumni8nKey());
            if (displayName != null) {
                rowHeaderColumn.setColumnDisplayName(displayName);
            }
        });
        return rowHeaderColumnList;
    }

    @Override
    public void modifyOneClickTermEnable(String termId, boolean enable) {
        OneClickTermDto oneClickTermDto = oneClickTermDao.findOne(termId);
        if (ConstantString.SYSTEM_DEFAULT_COMPANY_ID.equals(oneClickTermDto.getCompanyId())) {
            // 系统默认一键功能，不允许编辑
            throw new OneClickException("one_click_system_term_unable_to_edit", "系统默认一键功能，不允许编辑!");
        }
        oneClickTermDto.setEnable(enable);
        oneClickTermDao.save(oneClickTermDto);
    }
}
